package lock

import (
	"errors"
	"os"
	"syscall"
)

type Type int

const (
	Share   Type = syscall.LOCK_SH // 共享锁，读文件时使用
	Exclude Type = syscall.LOCK_EX // 排它锁，写文件时使用
)

//FileLock 文件锁
type FileLock struct {
	filePath string
	f        *os.File
	lockType Type
}

//NewFileLock 创建文件锁
func NewFileLock(filePath string, lockType Type) *FileLock {
	return &FileLock{
		filePath: filePath,
		lockType: lockType,
	}
}

//Lock 加锁
func (l *FileLock) Lock() (err error) {
	l.f, err = os.Open(l.filePath)
	if err != nil {
		return err
	}
	err = syscall.Flock(int(l.f.Fd()), int(l.lockType))
	if err != nil {
		return errors.New(l.filePath + "加文件锁失败：" + err.Error())
	}
	return
}

//Unlock 释放锁
func (l *FileLock) Unlock() error {
	defer l.f.Close()
	err := syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
	if err != nil {
		return errors.New(l.filePath + "解文件锁失败：" + err.Error())
	}
	return err
}
